package com.dianzhihan.cashier.service;

import com.dianzhihan.cashier.mapper.OrderItemMapper;
import com.dianzhihan.cashier.mapper.OrderMapper;
import com.dianzhihan.cashier.mapper.ProductMapper;
import com.dianzhihan.cashier.model.order.Order;
import com.dianzhihan.cashier.model.order.OrderDetail;
import com.dianzhihan.cashier.model.order.OrderItem;
import com.dianzhihan.cashier.model.order.OrderStatus;
import com.dianzhihan.cashier.model.product.Product;
import com.dianzhihan.cashier.model.user.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.relational.core.sql.In;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;

/**
 * @author Dianzhi Han
 * @version 1.0
 * @description: Order订单表的Service类
 * @date 2023/2/11 12:27
 */

@Service
@Slf4j
public class OrderService {

    private final ProductMapper productMapper;
    private final OrderMapper orderMapper;
    private final OrderItemMapper orderItemMapper;

    @Autowired
    public OrderService(ProductMapper productMapper, OrderMapper orderMapper, OrderItemMapper orderItemMapper) {
        this.productMapper = productMapper;
        this.orderMapper = orderMapper;
        this.orderItemMapper = orderItemMapper;
    }

    //购买商品(创建一个订单,设定成未支付状态，等待确认)
    @Transactional  //整体看作一个事务
    public Order create(User user, Map<Integer,Integer> toBoughtProductMap){ // toBoughtProductMap<商品 id, 要购买的数量>
        //1.从数据库中根据id查询products表，然后获得product来比对库存是否足够
        Map<Integer, Product> productMap = confirmStockIsEnough(toBoughtProductMap);
        log.debug("商品库存足够：productMap={}",productMap);

        //2.若库存足够，则减库存
       stockDecrement(toBoughtProductMap);
        //3.往Orders表中新增一条订单记录
        Order order = createOrder(user, productMap, toBoughtProductMap);
        //4.往Order_items表中新增n条订单项（根据订单id）
        createOrderItem(order, productMap, toBoughtProductMap);
        return order;
    }

    //4.往Order_items表中新增n条订单项（根据订单id）
    private void createOrderItem(Order order, Map<Integer, Product> productMap, Map<Integer, Integer> toBoughtProductMap) {
        Set<Integer> productIdSet = productMap.keySet();
        HashSet<OrderItem> orderItemsSet = new HashSet<>();
        //传给数据库的是OrderItemsSet，所以要传order，product 还有 购买的数量number
        for (Integer productId : productIdSet) {
            Product product = productMap.get(productId);
            int number = toBoughtProductMap.get(productId);
            OrderItem orderItem = new OrderItem(order,product,number);
            orderItemsSet.add(orderItem);
        }
        //批量插入，用一个Set，mapper.xml用动态SQL foreach就行
        orderItemMapper.insertBatch(orderItemsSet);

    }

    //3.往Orders表中新增一条订单记录
    private Order createOrder(User user, Map<Integer,Product> productMap, Map<Integer,Integer> toBoughtProductMap){
        //获得一个随机的32位数作为订单编号
        String uuid = generateUUID();
        //订单开始时间
        Timestamp createdAt = Timestamp.from(Instant.now());

        // 计算应付总额
        int payable = calculatePayable(productMap, toBoughtProductMap);
        // 计算实付总额
        int actual = calculateActual(productMap, toBoughtProductMap);
        // 初始状态
        OrderStatus status = OrderStatus.unpaid;

        Order order = new Order(user.getUserId(), uuid, createdAt, payable, actual, status);

        // OrderMapper 完成订单插入
        orderMapper.insert(order);
        log.debug("完成订单插入：order = {}", order);


        return order;

    }
    //计算实际总额
    private int calculateActual(Map<Integer, Product> productMap, Map<Integer, Integer> toBoughtProductMap) {
        int sum = 0;
        for (Map.Entry<Integer, Integer> entry : toBoughtProductMap.entrySet()) {
            int id = entry.getKey();
            int number = entry.getValue();
            Product product = productMap.get(id);
            int price = product.getPrice();
            double discount = product.getDiscount()/100.0;
            sum += (int)(price * discount * number); //小数点后面不要了
        }
        return sum;
    }

    // 计算应付总额
    private int calculatePayable(Map<Integer, Product> productMap, Map<Integer, Integer> toBoughtProductMap) {
        int sum = 0;
        for (Map.Entry<Integer, Integer> entry : toBoughtProductMap.entrySet()) {
            int id = entry.getKey();
            int number = entry.getValue();
            Product product = productMap.get(id);
            int price = product.getPrice();
            int payable = price * number;
            sum += payable;
        }
        return sum;
    }

    //获得一个随机的32位数作为订单编号
    private String generateUUID() {
        String s = UUID.randomUUID().toString();
        return s.replace("-", "");
    }

    //2.若库存足够，则减库存
    private void stockDecrement(Map<Integer, Integer> toBoughtProductMap) {
        for (Map.Entry<Integer, Integer> entry : toBoughtProductMap.entrySet()) {
            int productId = entry.getKey();
            int number = entry.getValue();

            productMapper.decrementStockByProductId(productId, number);
        }
    }


    //1.判断库存是否足够
    private Map<Integer, Product> confirmStockIsEnough(Map<Integer, Integer> toBoughtProductMap) {
        //首先得把这个商品ID提取出来
        Set<Integer> toBuyProductIdSet = toBoughtProductMap.keySet();

        //根据这个商品ID的集合，一个个去查询数据库,mybatis只能返回一个List
        List<Product> products = productMapper.selectProductListByProductIdSet(toBuyProductIdSet);

        //根据查到的products 去和toBoughtProductMap中的product来比对库存是否足够
        //先把list<product>转化成map<id，product>
        HashMap<Integer, Product> productsHashMap = new HashMap<>();
        for (Product product : products){
            productsHashMap.put(product.getProductId(),product);
        }

        // TODO: 这里暂时不考虑传入的商品 id在表中不存在的情况了
        // 比较库存是否够
        for (Map.Entry<Integer, Integer>  entry : toBoughtProductMap.entrySet()){
            int boughtNumber = entry.getValue();
            Product product = productsHashMap.get(entry.getKey());
            if (boughtNumber > product.getStock()){
                throw new RuntimeException("商品ID为："+product.getProductId().toString() +"库存不够");   // 说明我们这个商品的库存是不够的
            }
        }

        // 说明所有商品的库存都是够的
        return productsHashMap;
    }

    //确认订单，根据orderId
    @Transactional
    public void confirmOrder(int orderId){
        // 更新订单记录（状态变成paid，设置订单完成时间是当前时间）
        Timestamp finishedAt = Timestamp.from(Instant.now());
        OrderStatus status = OrderStatus.paid;

        orderMapper.updateConfirm(orderId, finishedAt, status);
    }

    //取消订单，事务回滚
    @Transactional
    public void cancelOrder(int orderId){
        //1.根据订单号查询item,得到number
        List<OrderItem> orderItems = orderItemMapper.selectByOrderId(orderId);
        Map<Integer,Integer> toBuyProductMap = new HashMap<>();
        for (OrderItem orderItem : orderItems) {
            int productId = orderItem.getProductId();
            int productNumber = orderItem.getProductNumber();
            toBuyProductMap.put(productId,productNumber);
        }
        //2.删除订单项
        orderItemMapper.deleteItemByOrderId(orderId);
        //3.删除订单
        orderMapper.deleteOrderByOrderId(orderId);
        //4.库存加回去
        for (Map.Entry<Integer, Integer> entry : toBuyProductMap.entrySet()) {
            int productId = entry.getKey();
            int number = entry.getValue();
            productMapper.stockIncrementByProductId(productId,number);
        }
    }


    //根据uuid查询Orders表
    public OrderDetail queryByUuid(String uuid) {

        OrderDetail orderDetail = orderMapper.queryByUuid(uuid);
        orderDetail.setItemList(orderItemMapper.selectAllByOrderId(orderDetail.getOrderId()));

        return orderDetail;
    }


    //获取订单表
    public List<Order> getList() {
        return orderMapper.selectAll();
    }
}
